package dao.util;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;

import dao.DAO;


public class DaoFactory
{
	
	
	/**
	 * @return
	 * @throws UnsupportedEncodingException
	 * @throws ClassNotFoundException
	 */
	public static Class<?>[] getDaoClasses() throws UnsupportedEncodingException, ClassNotFoundException
	{
		ClassLoader cld = DaoFactory.class.getClassLoader();
		return getClasses(DAO.class.getPackage().getName(), cld);
	}
	

	/**
	 * @param pckgname
	 * @param cld 
	 * @return
	 * @throws ClassNotFoundException
	 * @throws UnsupportedEncodingException
	 */
	@SuppressWarnings({ "rawtypes" })
	private static Class[] getClasses(String pckgname, ClassLoader cld)	throws ClassNotFoundException, UnsupportedEncodingException 
	{
		ArrayList<Class> classes = new ArrayList<Class>();
		// Get a File object for the package
		File directory = null;
		try 
		{
			if (cld == null) 
			{
				throw new ClassNotFoundException("Can't get class loader.");
			}
			String path = pckgname.replace('.', '/');
			URL resource = cld.getResource(path);
			if (resource == null) 
			{
				throw new ClassNotFoundException("No resource for " + path);
			}
			directory = new File(URLDecoder.decode(resource.getPath(),"UTF-8"));
			
			
			if (directory.exists()) 
			{
				// Get the list of the files contained in the package
				String[] files = directory.list();
				
				for (int i = 0; i < files.length; i++) 
				{
					// we are only interested in .class files
					if (files[i].endsWith(".class")) 
					{
						Class<?> dao = Class.forName(pckgname + '.' + files[i].substring(0, files[i].length() - 6));
						if(dao.isAnnotationPresent(DaoAnnotation.class))
						{
							classes.add(dao);
						}
					} 
					else if(!files[i].contains("."))
					{
						// recursive opening of subpackages
						
						Class[] klassen = getClasses(pckgname + "." + files[i], cld);
						for(Class klasse:klassen)
						{
							classes.add(klasse);
//							System.out.println("Test: "+((DaoAnnotation) klasse.getAnnotation(DaoAnnotation.class)).use());
						}
					}
				}
			} 
			else 
			{
				throw new ClassNotFoundException(pckgname+ " does not appear to be a valid film");
			}
			Class[] classesA = new Class[classes.size()];
			classes.toArray(classesA);
			return classesA;
		}
			catch (NullPointerException x) 
			{
				throw new ClassNotFoundException(pckgname + " (" + directory+ ") does not appear to be a valid film");
		}
	}
}
